import * as THREE from "three";
import type Experience from "./Experience";

/**
 * 加载动画组件
 * 使用 Three.js 绘制小米 SU7 车型轮廓
 */
export default class LoadingAnimation {
  base: Experience;
  scene: THREE.Scene;
  camera: THREE.OrthographicCamera;
  renderer: THREE.WebGLRenderer;
  line!: THREE.Line;
  totalLength: number = 0;
  currentLength: number = 0;
  progress: number = 0;
  percentageElement: HTMLElement | null;
  isComplete: boolean = false;

  // 小米 SU7 车型轮廓坐标（侧面视角）
  carOutlinePoints = [
    // 前车头（左侧）
    new THREE.Vector2(-6.0, 0.8),
     new THREE.Vector2(-5.9, 0.86),
     new THREE.Vector2(-5.7, 0.9),
    new THREE.Vector2(-5.5, 1.0),
     new THREE.Vector2(-5, 1.2),
    new THREE.Vector2(-4.0, 1.5),
    
    // 前挡风玻璃
    new THREE.Vector2(-3.0, 1.6),
    new THREE.Vector2(-2.5, 1.9),
    new THREE.Vector2(-2.0, 2.1),
    
    // 车顶
    new THREE.Vector2(-1.5, 2.2),
    new THREE.Vector2(-1.0, 2.35),
    new THREE.Vector2(0, 2.4),
     new THREE.Vector2(0.5, 2.43),
    new THREE.Vector2(1.0, 2.35),
    new THREE.Vector2(1.8, 2.2),
    
    // 后挡风玻璃
    new THREE.Vector2(2.3, 1.9),
    new THREE.Vector2(2.7, 1.7),
    new THREE.Vector2(3.0, 1.4),
    
    // 后车厢
    new THREE.Vector2(3.2, 1.2),
    new THREE.Vector2(3.5, 1.0),
    new THREE.Vector2(3.8, 0.9),
    new THREE.Vector2(4.2, 0.8),
  ];

  constructor(base: Experience, container: HTMLElement) {
    this.base = base;

    // 创建独立的 Three.js 场景用于加载动画
    this.scene = new THREE.Scene();
    this.scene.background = new THREE.Color("#000000");

    // 创建正交相机
    const aspect = window.innerWidth / window.innerHeight;
    const frustumSize = 5;
    this.camera = new THREE.OrthographicCamera(
      -frustumSize * aspect,
      frustumSize * aspect,
      frustumSize,
      -frustumSize,
      0.1,
      100
    );
    this.camera.position.z = 5;

    // 创建渲染器
    this.renderer = new THREE.WebGLRenderer({ antialias: true });
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    container.appendChild(this.renderer.domElement);

    // 获取百分比元素
    this.percentageElement = document.querySelector(".loading-percentage");

    // 创建车型轮廓线
    this.createCarOutline();

    // 计算总长度
    this.calculateTotalLength();

    // 监听窗口大小变化
    window.addEventListener("resize", this.onResize.bind(this));

    // 开始动画
    this.animate();
    
    // 初始化进度显示
    this.updateProgress(0);
  }

  /**
   * 创建车型轮廓线
   */
  createCarOutline() {
    // 使用 CatmullRomCurve3 创建平滑曲线
    const points3D = this.carOutlinePoints.map(
      (p) => new THREE.Vector3(p.x, p.y, 0)
    );
    const curve = new THREE.CatmullRomCurve3(points3D);
    const points = curve.getPoints(200); // 获取200个点使曲线更平滑

    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    geometry.setDrawRange(0, 0); // 初始不绘制任何点

    // 创建线条材质（注意：linewidth 在很多浏览器上不工作，使用默认值）
    const material = new THREE.LineBasicMaterial({
      color: 0xffffff,
      linewidth: 5, // 某些浏览器可能忽略此值
    });

    this.line = new THREE.Line(geometry, material);
    this.scene.add(this.line);
  }

  /**
   * 计算线条总长度
   */
  calculateTotalLength() {
    const positions = this.line.geometry.attributes.position;
    let length = 0;
    for (let i = 0; i < positions.count - 1; i++) {
      const p1 = new THREE.Vector3(
        positions.getX(i),
        positions.getY(i),
        positions.getZ(i)
      );
      const p2 = new THREE.Vector3(
        positions.getX(i + 1),
        positions.getY(i + 1),
        positions.getZ(i + 1)
      );
      length += p1.distanceTo(p2);
    }
    this.totalLength = length;
  }

  /**
   * 更新加载进度
   */
  updateProgress(progress: number) {
    this.progress = Math.min(progress, 1);

    // 获取几何体的总顶点数
    const positions = this.line.geometry.attributes.position;
    const totalPoints = positions.count;
    
    // 根据进度更新绘制范围（至少绘制2个点以显示线条）
    const drawCount = Math.max(2, Math.floor(totalPoints * this.progress));
    this.line.geometry.setDrawRange(0, drawCount);

    // 更新百分比显示
    if (this.percentageElement) {
      this.percentageElement.textContent = `${Math.round(this.progress * 100)}%`;
    }

    // 检查是否完成
    if (this.progress >= 1 && !this.isComplete) {
      this.isComplete = true;
      setTimeout(() => {
        this.complete();
      }, 500);
    }
  }

  /**
   * 动画循环
   */
  animate() {
    if (this.isComplete) return;

    requestAnimationFrame(this.animate.bind(this));
    this.renderer.render(this.scene, this.camera);
  }

  /**
   * 完成加载
   */
  complete() {
    // 淡出动画
    const canvas = this.renderer.domElement;
    canvas.style.transition = "opacity 0.5s";
    canvas.style.opacity = "0";

    setTimeout(() => {
      this.destroy();
    }, 500);
  }

  /**
   * 窗口大小变化
   */
  onResize() {
    const aspect = window.innerWidth / window.innerHeight;
    const frustumSize = 5;
    
    this.camera.left = -frustumSize * aspect;
    this.camera.right = frustumSize * aspect;
    this.camera.top = frustumSize;
    this.camera.bottom = -frustumSize;
    this.camera.updateProjectionMatrix();

    this.renderer.setSize(window.innerWidth, window.innerHeight);
  }

  /**
   * 销毁组件
   */
  destroy() {
    window.removeEventListener("resize", this.onResize.bind(this));
    
    if (this.renderer.domElement.parentElement) {
      this.renderer.domElement.parentElement.removeChild(
        this.renderer.domElement
      );
    }
    
    this.renderer.dispose();
    this.line.geometry.dispose();
    (this.line.material as THREE.Material).dispose();
  }
}
